﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "StructureRaftFoundation.h"
#include "AlgorithmCurveOperate.h"
#include "DbObjectUtils.h"
#include "GbmpBuiltInParameterDefinitionsNew.h"
#include "GbmpBuiltInParameterStaticVauleListItems.h"
#include "GcmpBuiltInParameterDefinitions.h"
#include "GmIStructureFactory.h"
#include "GmStructureDefaultElementParametersCustomizer.h"
#include "ICalculator.h"
#include "ICalculatorCollection.h"
#include "ICopyStrategyReporter.h"
#include "ICurve3d.h"
#include "IDocument.h"
#include "IElement.h"
#include "IElementParameters.h"
#include "IElementParentReporter.h"
#include "IElementPosition.h"
#include "IElementStatus.h"
#include "IElementTransformationComponent.h"
#include "IExternalDataComponent.h"
#include "IFamily.h"
#include "IGenericElement.h"
#include "IGraphicsCurve3d.h"
#include "IInstance.h"
#include "IInstanceType.h"
#include "IModelLine.h"
#include "IParameter.h"
#include "IParameterDefinitionLibrary.h"
#include "IPositionAssociatedPlane.h"
#include "IPositionPoint2d.h"
#include "IRegenerator.h"
#include "IRegeneratorDataIdCreator.h"
#include "InstancePlacementTypes.h"
#include "LevelUtils.h"
#include "ProfileUsedModelLineUtils.h"
#include "StructureInstanceLevelUtils.h"
#include "StructureProfileInstanceInput.h"
#include "StructureProfileInstanceUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

namespace gcmp
{
    class StructureRaftFoundationElementParametersCustomizer : 
        public GmStructureDefaultElementParametersCustomizer
    {
        DBOBJECT_DATA_BEGIN(gcmp, StructureRaftFoundationElementParametersCustomizer, 
            gcmp::GmStructureDefaultElementParametersCustomizer, 
            46670D23-605E-4D9A-B441-80A3A21A9B0D, gmstructure)
        DBOBJECT_DATA_END
    public:
        StructureRaftFoundationElementParametersCustomizer(IElement* pElement);

        virtual bool IsPresetParameter(const UniIdentity& paramDefUid) const override;
    };
}

DBOBJECT_DATA_DEFINE(StructureRaftFoundationElementParametersCustomizer)
{
    SetOwnerElement(nullptr);
}

StructureRaftFoundationElementParametersCustomizer::StructureRaftFoundationElementParametersCustomizer(
    IElement* pElement) : GmStructureDefaultElementParametersCustomizer(pElement)
{
}

bool StructureRaftFoundationElementParametersCustomizer::IsPresetParameter(const UniIdentity& paramDefUid) const
{
    if (paramDefUid.HasSameValue(PARAMETER_UID(TopAssociatedLevelBuiltInParameter)) ||
        paramDefUid.HasSameValue(PARAMETER_UID(BuildingStoreyBuiltInParameter)) ||
        paramDefUid.HasSameValue(PARAMETER_UID(TopOffsetBuiltInParameter)) ||
        paramDefUid.HasSameValue(PARAMETER_UID(RaftFoundationZPositioningTypeBuiltInParameter)) ||
        paramDefUid.HasSameValue(PARAMETER_UID(ConcreteStrengthGradeBuiltInParameter)))
    {
        return true;
    }

    return false;
}

IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureRaftFoundation, Volume)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureRaftFoundation, Area)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureRaftFoundation, TopElevation)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureRaftFoundation, BottomElevation)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, StructureRaftFoundation, RaftFoundationShapeChanged)

DEFINE_STRUCTURE_INSTANCE_METHODS(StructureRaftFoundation);

DBOBJECT_DATA_DEFINE(StructureRaftFoundation)
{
    m_pOwnerElement = nullptr;
    SetVolume__(0);
    SetArea__(0);
    SetTopElevation__(0);
    SetBottomElevation__(0);
    SetConcreteStrengthGrade__(ConcreteStrengthGradeType::CSG_C30);
}

gcmp::StructureRaftFoundation* StructureRaftFoundation::Create(const StructureRaftFoundationGeometryInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    const IPolygon* pPolygon = pInput->ProfilePolygon.get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPolygon, L"pPolygon为空",L"GDMPLab",L"2024-03-30");

    ElementId associatedPlaneId = pInput->AssociatedPlaneId;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(associatedPlaneId.IsValid(), L"associatedPlaneId无效",L"GDMPLab",L"2024-03-30");
    
    OwnerPtr<StructureRaftFoundationElementInput> pElementInput = NEW_AS_OWNER_PTR(StructureRaftFoundationElementInput);

    std::vector<IModelLine*> profileCurves;
    bool bOk = StructureProfileInstanceUtils::GenerateProfileCurvesFromPolygon(pDoc, pPolygon, associatedPlaneId, profileCurves);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"ProfileCurves生成失败",L"GDMPLab",L"2024-03-30");

    // 构造一个StructureFloorSlopeLine
    const StructureFloorSlopeLineInput* pSlopeLineInput = pInput->FloorSlopeLine.get();
    IStructureSlopeLine* pSlopeLine = nullptr;
    if (pSlopeLineInput)
    {
        pSlopeLine = StructureProfileInstanceUtils::GenerateStructureFloorSlopeLine(pDoc, pSlopeLineInput);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlopeLine, L"SlopeLine生成失败",L"GDMPLab",L"2024-03-30");
    }

    // 继承自StructureInstanceInput的参数
    pElementInput->Document = pDoc;
    pElementInput->AssociatedPlaneId = associatedPlaneId;
    pElementInput->StoreyId = pInput->StoreyId;
    pElementInput->FamilyId = pInput->FamilyId;
    pElementInput->InstanceTypeId = pInput->InstanceTypeId;
    pElementInput->CreationOption = pInput->CreationOption;
    pElementInput->CanBeShared = pInput->CanBeShared;
    pElementInput->Visible = pInput->Visible;
    // 继承自StructureProfileInstanceGeometryInput的参数
    pElementInput->ProfileCurves = profileCurves;
    pElementInput->FloorSlopeLine = pSlopeLine;
    pElementInput->AssociatedPlaneId = pInput->AssociatedPlaneId;
    pElementInput->ConcreteType = pInput->ConcreteType;
    // StructureRaftFoundationElementInput的参数
    pElementInput->ZPositioningType = pInput->ZPositioningType;
    pElementInput->AssociatedPlaneOffset = pInput->AssociatedPlaneOffset;

    // 调用API创建筏板
    StructureRaftFoundation* pRaftFoundation = StructureRaftFoundation::Create(pElementInput.get());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pRaftFoundation, L"pFloor为空",L"GDMPLab",L"2024-03-30");

    return pRaftFoundation;
}

StructureRaftFoundation* StructureRaftFoundation::Create(const StructureRaftFoundationElementInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IInstanceType* pInstanceType = quick_cast<IInstanceType>(pDoc->GetElement(pInput->InstanceTypeId));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");

    IInstance* pInstance = pInstanceType->CreateInstance(L"筏板实例", pInput->CanBeShared, pInput->CreationOption, pInput->IsCreateGeometryRelationshipComponent);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    IElementStatus* pStatus = pInstance->GetStatus();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStatus, L"无法获取状态集",L"GDMPLab",L"2024-03-30");
    pStatus->SetIsVisible(pInput->Visible);

    //设置实例外部自定义数据
    StructureRaftFoundation* pRaftFoundation = StructureRaftFoundation::RegisterExternalData(pInstance);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pRaftFoundation, L"pFloor为空",L"GDMPLab",L"2024-03-30");
    pRaftFoundation->SetConcreteStrengthGrade(pInput->ConcreteType);
    //模型线
    std::vector<IModelLine*> profileCurves = pInput->ProfileCurves;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!profileCurves.empty(), L"profileCurves为空",L"GDMPLab",L"2024-03-30");
    //更新Instance
    bool bOk = pRaftFoundation->UpdateRaftProfiles(profileCurves);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"更新Instance无效",L"GDMPLab",L"2024-03-30");

    std::vector<OwnerPtr<ICurve3d>> profileICurvesOwner;
    std::vector<const ICurve3d*> profileICurves;
    std::vector<OwnerPtr<ICurve3d>> outerCurves; // 外圈轮廓
    std::vector<int> outerIndexes;
    for (auto& pModelLine : profileCurves)
    {
        OwnerPtr<ICurve3d> opCurve3d = pModelLine->GetGeometryCurve();
        profileICurves.push_back(opCurve3d.get());
        profileICurvesOwner.push_back(TransferOwnership(opCurve3d));
    }
    gcmp::AlgorithmCurveOperate::CreateSequencedCurves(profileICurves, outerCurves, outerIndexes);

    // 计算一个插值点
    Vector3d insertPt = Vector3d::Zero;
    {
        Box3d box;
        FOR_EACH(curve, outerCurves)
        {
            box.MergeBox(curve->GetBox());
        }
        insertPt = box.GetCenter();
    }

    ElementId topLevelId = pInput->AssociatedPlaneId;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(topLevelId.IsValid(), L"topLevelId无效",L"GDMPLab",L"2024-03-30");

    const ILevel* pStoreyLevel=nullptr;
    if (pInput->StoreyId.IsValid())
    {
        pStoreyLevel = LevelUtils::GetLevelById(pDoc, pInput->StoreyId);
    }
    else
    {
        pStoreyLevel = StructureInstanceLevelUtils::GetRaftFoundationStoreyLevelFromPositioningLevel(pDoc, topLevelId);
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStoreyLevel, L"pStoreyLevel为空",L"GDMPLab",L"2024-03-30");

    bOk = StructureInstanceLevelUtils::CreateInstanceStoreyLevel(pInstance, pStoreyLevel);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"设置筏板的StoreyLevel失败",L"GDMPLab",L"2024-03-30");

    // 以插入点为原点坐标系
    Coordinate3d baseCoord(insertPt, Vector3d::UnitX, Vector3d::UnitY);
    OwnerPtr<IPolygon> opPolygon = StructureProfileInstanceUtils::CalculateProfilePolygon(profileICurves, baseCoord);

    bOk = IElementPosition::CreatePoint2dOnTopAssociatedPlanePositionBehavior(pInstance,
        topLevelId, baseCoord.GetOrigin(), baseCoord.GetX(), baseCoord.GetY());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"PositionBehavior创建失败",L"GDMPLab",L"2024-03-30");
    IPositionAssociatedPlane::SetBottomPlaneHeightOffset(pInstance, pInput->AssociatedPlaneOffset);

    if (opPolygon)
    {
        bool bOk = StructureProfileInstanceUtils::SetProfileByCurveArray(opPolygon.get(), baseCoord, pInstance);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"更新轮廓曲线失败",L"GDMPLab",L"2024-03-30");
    }

    IElementParameters* pElementParameters = pInstance->GetElementParameters();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementParameters, L"paramZPositioningType无效",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IParameter> paramZPositioningType = pElementParameters->GetParameterByUid(PARAMETER_UID(RaftFoundationZPositioningTypeBuiltInParameter));

    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(IParameter::IsValidParameter(paramZPositioningType), L"paramZPositioningType无效",L"GDMPLab",L"2024-03-30");
    paramZPositioningType->SetValueAsInt((int)pInput->ZPositioningType);
    pElementParameters->SetParameter(paramZPositioningType.get());

    OwnerPtr<IParameter> paramPlacementType = ELEMENT_PARAMETER(pInstance, InstancePlacementTypeBuiltInParamter);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(IParameter::IsValidParameter(paramPlacementType), L"placementType参数获取失败",L"GDMPLab",L"2024-03-30");
    InstancePlacementTypes placementType = (InstancePlacementTypes)paramPlacementType->GetValueAsInt();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(placementType == InstancePlacementTypes::FamilyBasedOnProfile, L"placementType参数获取失败",L"GDMPLab",L"2024-03-30");

    ProfileUsedModelLineUtils::SetAssociatedInstanceIdForModelLines(profileCurves, pInstance->GetElementId());
    if (pInstance->GetElementParameters())
    {
        OwnerPtr<IElementParametersCustomizer> opNewCustomizer = 
            NEW_AS_OWNER_PTR(StructureRaftFoundationElementParametersCustomizer, pInstance);
        GmStructureDefaultElementParametersCustomizer::SetElementParametersCustomizer(
            pInstance, TransferOwnership(opNewCustomizer));
    }

    // 将模型线从世界坐标系转换到楼板的局部坐标系，这样以后就可以根据楼板PositionHelper位置更新模型线的位置。
    const IElementPosition *posBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posBehavior, L"posBehavior不能为空",L"GDMPLab",L"2024-03-30");

    Matrix4d mat = posBehavior->ComputeLocalToWorldCoordinateSystemTransformMatrix();
    bOk = mat.MakeInverse();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"MakeInverse失败",L"GDMPLab",L"2024-03-30");

    FOR_EACH(pModelLine, profileCurves)
    {
        pModelLine->GetOwnerElement()->GetStatus()->SetIsVisible(false);
        //设置轮廓线在基准面上的偏移
        IGenericElement* pGenericElement = quick_cast<IGenericElement> (pModelLine->GetOwnerElement());
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement, L"获取pGenericElement为空！",L"GDMPLab",L"2024-03-30");

        IElementPosition* pModelLineElementPosition = pGenericElement->GetElementPosition();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelLineElementPosition, L"获取pElementPosition为空！",L"GDMPLab",L"2024-03-30");

        IPositionAssociatedPlane* pAssociatedPlane = pModelLineElementPosition->GetPositionAssociatedPlane();
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pAssociatedPlane, L"获取pAssociatedPlane为空！",L"GDMPLab",L"2024-03-30");

        pAssociatedPlane->SetBasePlaneOffset(pInput->AssociatedPlaneOffset);
        pModelLine->GetOwnerElement()->GetElementTransformationComponent()->Transform(mat);
    }

    bool isOk = pDoc->GetRegenerator()->RegenerateElement(pInstance->GetElementId());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(isOk, L"RegenerateElement失败",L"GDMPLab",L"2024-03-30");

    return StructureRaftFoundation::Get(pInstance);
}

gcmp::StructureRaftFoundation* StructureRaftFoundation::Edit(const StructureProfileInstanceEditGeometryInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    const IPolygon* pPolygon = pInput->ProfilePolygon.get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPolygon, L"pPolygon为空",L"GDMPLab",L"2024-03-30");

    ElementId instanceId = pInput->InstanceId;
    IInstance* pInstance = quick_cast<IInstance>(pDoc->GetElement(instanceId));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    const IElementPosition* posBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posBehavior, L"posBehavior为空",L"GDMPLab",L"2024-03-30");
    const IPositionAssociatedPlane* posAssociatedPlane = quick_cast<const IPositionAssociatedPlane>(posBehavior->GetPositionAssociatedPlane());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posAssociatedPlane, L"posAssociatedPlane为空",L"GDMPLab",L"2024-03-30");
    ElementId associatedPlaneId = posAssociatedPlane->GetBasePlaneElementId();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(associatedPlaneId.IsValid(), L"associatedPlaneId无效",L"GDMPLab",L"2024-03-30");

    std::vector<IModelLine*> profileCurves;
    bool bOk = StructureProfileInstanceUtils::GenerateProfileCurvesFromPolygon(pDoc, pPolygon, associatedPlaneId, profileCurves);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"ProfileCurves生成失败",L"GDMPLab",L"2024-03-30");

    // 构造一个StructureFloorSlopeLine
    const StructureFloorSlopeLineInput* pSlopeLineInput = pInput->FloorSlopeLine.get();
    IStructureSlopeLine* pSlopeLine = nullptr;
    if (pSlopeLineInput)
    {
        pSlopeLine = StructureProfileInstanceUtils::GenerateStructureFloorSlopeLine(pDoc, pSlopeLineInput);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pSlopeLine, L"SlopeLine生成失败",L"GDMPLab",L"2024-03-30");
    }

    OwnerPtr<StructureProfileInstanceEditElementInput> pElementInput = NEW_AS_OWNER_PTR(StructureProfileInstanceEditElementInput);
    pElementInput->Document = pDoc;
    pElementInput->InstanceId = instanceId;
    pElementInput->ProfileCurves = profileCurves;
    pElementInput->FloorSlopeLine = pSlopeLine;

    // 调用API编辑筏板
    StructureRaftFoundation* pRaftFoundation = StructureRaftFoundation::Edit(pElementInput.get());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pRaftFoundation, L"pFloor为空",L"GDMPLab",L"2024-03-30");

    return pRaftFoundation;
}

gcmp::StructureRaftFoundation* StructureRaftFoundation::Edit(const StructureProfileInstanceEditElementInput* pInput)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInput, L"pInput为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pInput->Document;
    DBG_WARN_AND_RETURN_UNLESS(pDoc != nullptr, nullptr, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    ElementId idInstance = pInput->InstanceId;
    IInstance *pInstance = quick_cast<IInstance>(pDoc->GetElement(idInstance));
    DBG_WARN_AND_RETURN_UNLESS(pInstance != nullptr, nullptr, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    const IElementPosition *posBehavior = pInstance->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posBehavior, L"posBehavior为空",L"GDMPLab",L"2024-03-30");

    const IPositionPoint2d *posPoint2d = dynamic_cast<const IPositionPoint2d*>(posBehavior->GetPositionGeometry());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posPoint2d, L"posPoint2d为空",L"GDMPLab",L"2024-03-30");

    const IPositionAssociatedPlane *posAssociatedPlane = dynamic_cast<const IPositionAssociatedPlane*>(posBehavior->GetPositionAssociatedPlane());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(posAssociatedPlane, L"posAssociatedPlane为空",L"GDMPLab",L"2024-03-30");

    StructureRaftFoundation* pRaftFoundation = StructureRaftFoundation::Get(pInstance);
    DBG_WARN_AND_RETURN_UNLESS(pRaftFoundation, nullptr, L"获取板的externalData失败！",L"GDMPLab",L"2024-03-30");

    std::vector<IModelLine*> profileCurves = pInput->ProfileCurves;
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!profileCurves.empty(), L"profileCurves为空",L"GDMPLab",L"2024-03-30");

    //更新Instance
    bool bOk = pRaftFoundation->UpdateRaftProfiles(profileCurves);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"更新Instance无效",L"GDMPLab",L"2024-03-30");

    std::vector<OwnerPtr<ICurve3d>> profileICurvesOwner;
    std::vector<const ICurve3d*> profileICurves;
    std::vector<OwnerPtr<ICurve3d>> outerCurves; // 外圈轮廓
    std::vector<int> outerIndexes;
    for (auto& pModelLine : profileCurves)
    {
        OwnerPtr<ICurve3d> opCurve3d = pModelLine->GetGeometryCurve();
        profileICurves.push_back(opCurve3d.get());
        profileICurvesOwner.push_back(TransferOwnership(opCurve3d));
    }
    gcmp::AlgorithmCurveOperate::CreateSequencedCurves(profileICurves, outerCurves, outerIndexes);

    ProfileUsedModelLineUtils::SetAssociatedInstanceIdForModelLines(profileCurves, pInstance->GetElementId());

    // 如果Instance是镜像的，它的LcsToWcsTransformMatrix中是含有镜像信息的，这边需要做处理。
    OwnerPtr<IParameter> mirrorParam = ELEMENT_PARAMETER(pInstance, InstanceMirrorSignBuiltInParameter);
    bool isMirror = IParameter::IsValidParameter(mirrorParam) && mirrorParam->GetValueAsBool();
    if (isMirror)
    {
        //因为镜像后实体坐标系变成了(-X,-Y), 因此需要将看到的(X,Y)坐标系下的轮廓线变换到实体坐标系上
        Matrix4d mat = posBehavior->ComputeLocalToWorldCoordinateSystemTransformMatrix();
        Matrix4d matInverse;
        bOk = mat.GetInverse(matInverse);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"GetInverse失败",L"GDMPLab",L"2024-03-30");

        Matrix4d matMirror;
        matMirror.MakeMirror(Vector3d::Zero, Vector3d::UnitY);
        FOR_EACH(pProfileCurve, profileICurvesOwner)
        {
            //世界坐标系变回局部坐标系
            pProfileCurve->Transform(matInverse);
            // 在局部坐标系将轮廓镜像
            pProfileCurve->Transform(matMirror);
            // 最后从局部坐标系再变换回世界坐标系
            pProfileCurve->Transform(mat);
        }
    }

    // 保持原有插入点的位置
    Vector3d insertPt(posPoint2d->GetOrigin(), posAssociatedPlane->GetBasePlaneHeight());
    Coordinate3d baseCoord(insertPt, posPoint2d->GetDirectionX(), posPoint2d->GetDirectionY());
    OwnerPtr<IPolygon> opPolygon = StructureProfileInstanceUtils::CalculateProfilePolygon(profileICurves, baseCoord);
    std::wstring strPolygon = opPolygon->GetStringForDebug();

    if (!StructureProfileInstanceUtils::SetProfileByCurveArray(opPolygon.get(), baseCoord, pInstance))
    {
        return nullptr;
    }

    Matrix4d mat = posBehavior->ComputeLocalToWorldCoordinateSystemTransformMatrix();
    bOk = mat.MakeInverse();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"MakeInverse失败",L"GDMPLab",L"2024-03-30");

    FOR_EACH(pModelLine, profileCurves)
    {
        pModelLine->GetOwnerElement()->GetStatus()->SetIsVisible(false);
        pModelLine->GetOwnerElement()->GetElementTransformationComponent()->Transform(mat);
    }

    IElementStatus* pStatus = pInstance->GetStatus();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pStatus, L"无法获取状态集",L"GDMPLab",L"2024-03-30");
    pStatus->SetIsVisible(true);
    bOk = pDoc->GetRegenerator()->RegenerateElement(pInstance->GetElementId());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"RegenerateElement失败",L"GDMPLab",L"2024-03-30");
    return StructureRaftFoundation::Get(pInstance);
}

gcmp::StructureRaftFoundation* StructureRaftFoundation::Get(IInstance* pInstance)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");
    if (IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        IExternalData *pData = pExternalDataComponent->FindExternalData(StructureRaftFoundation::GetStaticClassSchema()->GetName());
        if (!pData)
        {
            return nullptr;
        }
        return quick_cast<StructureRaftFoundation>(pData);
    }
    return nullptr;
}

const gcmp::StructureRaftFoundation* StructureRaftFoundation::Get(const IInstance* pInstance)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    if (const IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        const IExternalData* pData = pExternalDataComponent->FindExternalData(StructureRaftFoundation::GetStaticClassSchema()->GetName());
        if (!pData)
        {
            return nullptr;
        }
        return quick_cast<StructureRaftFoundation>(pData);
    }
    return nullptr;
}


void StructureRaftFoundation::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
    FOR_EACH (id, deletedElementIds)
    {
        auto it = std::find(GetProfileIdsFW__().begin(), GetProfileIdsFW__().end(), id);
        if (it != GetProfileIdsFW__().end())
        {
            GetProfileIdsFW__().erase(it);
        }
    }
}

void StructureRaftFoundation::ReportParents(IElementParentReporter& reporter) const
{
    FOR_EACH(id, GetProfileIds__())
    {
        reporter.ReportWeak(id);
    }
}

DECLARE_CALCULATOR_CREATOR(InstanceVolumeCalculator)
DECLARE_CALCULATOR_CREATOR(StructureRaftFoundationBottomAreaCalculator)
DECLARE_CALCULATOR_CREATOR(StructureRaftFoundationTopElevationCalculator)
DECLARE_CALCULATOR_CREATOR(StructureRaftFoundationBottomElevationCalculator)

void StructureRaftFoundation::GetCalculators(ICalculatorCollection * calculators) const
{
    ADD_CALCULATOR(InstanceVolumeCalculator, GetDocument(), GetVolumeRdId());
    ADD_CALCULATOR(StructureRaftFoundationBottomAreaCalculator, GetDocument(), GetAreaRdId());
    ADD_CALCULATOR(StructureRaftFoundationTopElevationCalculator, GetDocument(), GetTopElevationRdId());
    ADD_CALCULATOR(StructureRaftFoundationBottomElevationCalculator, GetDocument(), GetBottomElevationRdId());
}

void StructureRaftFoundation::ReportParameterDefinitions(std::vector<int>* pParamDefIds) const
{
    if (!quick_cast<IRegenerator>(GetDocument()->GetRegenerator())->IsRegerating())
    {
        pParamDefIds->push_back(PARAMETER_ID(AreaBuiltInParameter));
        pParamDefIds->push_back(PARAMETER_ID(VolumeBuiltInParameter));
        pParamDefIds->push_back(PARAMETER_ID(TopElevationBuiltInParameter));
        pParamDefIds->push_back(PARAMETER_ID(BottomElevationBuiltInParameter));
        pParamDefIds->push_back(PARAMETER_ID(ConcreteStrengthGradeBuiltInParameter));
    }
}

OwnerPtr<IParameter> StructureRaftFoundation::GetNativeParameter(int paramDefId) const
{
    OwnerPtr<IParameter> param;
    ParameterAttributes pa = {false, false, true};
    if (paramDefId == PARAMETER_ID(VolumeBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(VolumeBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(VolumeBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetVolume());
        return TransferOwnership(param);
    }
    else if (paramDefId == PARAMETER_ID(AreaBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(AreaBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(AreaBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetArea());
        return TransferOwnership(param);
    }
    else if (paramDefId == PARAMETER_ID(TopElevationBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(TopElevationBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(TopElevationBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetTopElevation());
        return TransferOwnership(param);
    }
    else if (paramDefId == PARAMETER_ID(BottomElevationBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Double, false, false,
            //true, PARAMETER_UID(BottomElevationBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Double, pa,
            PARAMETER_UID(BottomElevationBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsDouble(GetBottomElevation());
        return TransferOwnership(param);
    }
    else if (paramDefId == PARAMETER_ID(ConcreteStrengthGradeBuiltInParameter))
    {
        //param = NEW_AS_OWNER_PTR(Parameter, GetDocument(), ParameterStorageType::Int, false, false,
            //true, PARAMETER_UID(ConcreteStrengthGradeBuiltInParameter), ParameterProcessType::GeneralOutput);
        param = IParameter::CreateParameter(GetDocument(), ParameterStorageType::Int, pa,
            PARAMETER_UID(ConcreteStrengthGradeBuiltInParameter), ParameterProcessType::GeneralOutput);
        param->SetValueAsInt((int)GetConcreteStrengthGrade__());
        return TransferOwnership(param);
    }
    return nullptr;
}

bool StructureRaftFoundation::SetNativeParameter(const IParameter *param, std::wstring* errorMsg/* = nullptr*/)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(param, L"param is null.",L"GDMPLab",L"2024-03-30");

    if (param->GetParameterDefinitionId() == PARAMETER_ID(VolumeBuiltInParameter))
    {
        SetVolume(param->GetValueAsDouble());
        return true;
    }
    else if (param->GetParameterDefinitionId() == PARAMETER_ID(AreaBuiltInParameter))
    {
        SetArea(param->GetValueAsDouble());
        return true;
    }
    else if (param->GetParameterDefinitionId() == PARAMETER_ID(TopElevationBuiltInParameter))
    {
        SetTopElevation(param->GetValueAsDouble());
        return true;
    }
    else if (param->GetParameterDefinitionId() == PARAMETER_ID(BottomElevationBuiltInParameter))
    {
        SetBottomElevation(param->GetValueAsDouble());
        return true;
    }
    else if (param->GetParameterDefinitionId() == PARAMETER_ID(ConcreteStrengthGradeBuiltInParameter))
    {
        SetConcreteStrengthGrade((ConcreteStrengthGradeType)param->GetValueAsInt());
        return true;
    }
    return false;
}

bool StructureRaftFoundation::IsParameterModifiable(int paramDefId) const
{
    if (paramDefId == PARAMETER_ID(VolumeBuiltInParameter)||
        paramDefId == PARAMETER_ID(AreaBuiltInParameter)||
        paramDefId == PARAMETER_ID(TopElevationBuiltInParameter)||
        paramDefId == PARAMETER_ID(BottomElevationBuiltInParameter))
    {
        return false;
    }
    return true;
}

void StructureRaftFoundation::Report(const ICopyContext & copyContext, ICopyStrategyReporter& reporter) const
{
    reporter.ReportToCopy(GetOwnerElementId());

    FOR_EACH(id, GetProfileIds__())
    {
        reporter.ReportToCopy(id);
    }
}

IDocument* StructureRaftFoundation::GetDocument() const
{
    return m_pOwnerElement ? m_pOwnerElement->GetDocument() : nullptr;
}

ElementId StructureRaftFoundation::GetOwnerElementId() const
{
    return m_pOwnerElement ? m_pOwnerElement->GetElementId() : ElementId::InvalidID;
}

NdbObject* StructureRaftFoundation::GetTopOwnerObject() const
{
    if (!GetDocument())
        return nullptr;

    return quick_cast<NdbObject>(GetDocument()->GetElement(GetOwnerElementId()));
}

StructureRaftFoundation* StructureRaftFoundation::RegisterExternalData(IInstance* pInstance)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstance, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<StructureRaftFoundation> opRaftFoundation = NEW_AS_OWNER_PTR(StructureRaftFoundation);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opRaftFoundation, L"opRaftFoundation为空",L"GDMPLab",L"2024-03-30");
    opRaftFoundation->SetOwnerElement(pInstance);

    StructureRaftFoundation* pRaftFoundation = opRaftFoundation.get();
    if (IExternalDataComponent * pExternalDataComponent = pInstance->GetExternalDataComponent())
    {
        pExternalDataComponent->RegisterExternalData(StructureRaftFoundation::GetStaticClassSchema()->GetName(), TransferOwnership(opRaftFoundation));
    }
    return pRaftFoundation;
}

bool StructureRaftFoundation::Transform(const Matrix4d& matrix)
{
    Matrix4d matMirrorLocal;
    matMirrorLocal.MakeMirror(Vector3d::Zero, Vector3d::UnitY);

    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc != nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    auto profileIds = GetProfileIds();
    FOR_EACH(id, profileIds)
    {
        IElement* pProfileLineElement = pDoc->GetElement(id);
        if (pProfileLineElement)
        {
            if (!pProfileLineElement->GetElementPosition()->Transform(matMirrorLocal))
                return false;
        }
    }

    return true;
}

OwnerPtr<IPolygon> gcmp::StructureRaftFoundation::GetProfilePolygon() const
{
    IDocument* pDoc = GetDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    std::vector<ElementId> profileIds = GetProfileIds();
    std::vector<IModelLine*> profileCurves;
    bool bOk = ProfileUsedModelLineUtils::GetModelLinesUsedForProfileByElementIds(pDoc, profileIds, profileCurves);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"获取ModelLinesUsedForProfile失败",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IPolygon> opPolygon;
    Coordinate3d polygonCoord(Vector3d(0, 0, 0), Vector3d::UnitX, Vector3d::UnitY);
    bOk = StructureProfileInstanceUtils::GeneratePolygonFromProfileCurves(profileCurves, opPolygon, polygonCoord);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"Polygon生成失败",L"GDMPLab",L"2024-03-30");

    // 将轮廓线从局部坐标系转换回世界坐标系
    const IElementPosition *pElementPosition = m_pOwnerElement->GetElementPosition();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementPosition, L"pElementPosition为空",L"GDMPLab",L"2024-03-30");
    Matrix4d mat = pElementPosition->ComputeLocalToWorldCoordinateSystemTransformMatrix();
    opPolygon->Transform(mat);

    return opPolygon;
}

bool gcmp::StructureRaftFoundation::UpdateRaftProfiles(const std::vector<IModelLine*> profileCurves)
{
    std::vector<ElementId> profileIds;
    FOR_EACH(pModelLine, profileCurves)
    {
        profileIds.push_back(pModelLine->GetOwnerElement()->GetElementId());
    }
    this->SetProfileIds(profileIds);
    return true;
}